#ifndef _IMAGE_HPP_
#define _IMAGE_HPP_

#include <vector>
#include <boost/gil/virtual_locator.hpp>
#include <boost/gil/image_view.hpp>

#include "../ged/typedefs.hpp"
#include "ImageLayer.hpp"
#include "../gil/flattened_view.hpp"

namespace gil = boost::gil;

// template <typename T> class gil::flatten_deref_fn<T>;

namespace ged {

//! Klasa reprezentująca obrazek posiadający wiele warstw
/*!
 * Obrazek posiada stos warstw (ged::ImageLayer), z których każda jest
 * skojarzona z dokładnie jednym obrazkiem GIL
 * (boost::gil::image<>). Warstwa położona najniżej na stosie stanowi
 * tło obrazka i okręśla jego rozmiary oraz początek układu
 * współrzędnych. Obrazek dostarcza wirtualnego widoku GIL
 * (boost::gil::image_view<>), w którym warstwy położne wyżej na
 * stosie przykrywają warstwy położone poniżej.
 *
 * \sa ged::ImageLayer
 */
class Image {
private:
	//! Typ przechowywanej warstwy
	typedef PImageLayer element_type;
	//! Typ kontenera przechowującego stos warstw
	typedef std::vector<element_type> container_type;

	//! Typ funktora dostępu do wartości piksela w spłaszczonym widoku
	typedef gil::flatten_deref_fn<GILImageView, container_type> deref_type;
	//! Typ lokalizatora piksela w spłaszczony widoku
	typedef gil::virtual_2d_locator<deref_type, false> locator_type;
	//! Typ spłaszczonego widoku obrazka
	typedef gil::image_view<locator_type> flattened_view_type;

public:
	//! Typ wirtualnego widoku GIL na obrazek
	typedef flattened_view_type view_type;

	//! Konstruktor
	/*!
	 * \param sz rozmiar tła obrazka
	 */
	Image(const GILPoint& sz);

	//!Dodanie nowej warstwy
	/*
	 *\param image obraz GIL skojarzony z warstwą
	*/
	void addLayer(PGILImage image);

	//!Pobieranie aktywnej warstwy
	/*
	 *\return zwraca aktywną warstwę
	*/
	const PImageLayer getLayer() const;

	//! Wybór warstwy
	/*
	 *\param i indeks wybranej warstwy
	*/
	void selectLayer(std::size_t i);

	//! Pobieranie indeksu aktywnej warstwy
	/*
	 *\return zwraca indeks na stosie aktualnie wybranej warstwy
	*/
	int getActiveLayer() const;

	//! Usuwa warstwę
	/*!
	 * Usuwa warstwę znajdującą się najwyżej na stosie, a
	 * następnie wybiera wartstwę znajdującą się tuż pod usuniętą
	 * wartstwą jeżeli taka istnieje.
	 */
	void deleteLayer();

	//! Zwraca ilość warstw w obrazku
	inline std::size_t getCount() const { return layers_.size(); }

	//! Zwraca wirtualny "spłaszczony" widok GIL na obrazek
	/*!
	 * Wirtualny "spłaszony" widok GIL (boost::gil::image_view<>)
	 * generowany jest na podstawie stosu warstw, gdzie wyżej
	 * położona warstwa przykrywa te położone poniżej. Rozmiar
	 * obrazka dopasowany jest do rozmiaru najniższej warstwy.
	 *
	 * \return wirtualny "spłaszczony" widok GIL na obrazek
	 */
	const view_type getView() ;

private:
	// Wirtualny widok GIL na obrazek
	view_type view_;

	//! Indeks na stosie aktualnie wybranej warstwy
	int selected_idx_;

	//! Stos warstw
	/*!
	 * Warstwy znajdujące się wyżej na stosie przykrywają te
	 * znajdujące się niżej.
	 */
	container_type layers_;

	//! Tworzy wirtualny widok GIL dla obrazka
	/*!
	 * \param sz rozmiar widoku
	 */
	void initView(const GILPoint& sz);
};

} // namespace ged

#endif // _IMAGE_HPP_
